home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * BspBoehm.c - Implements Boehm single knot insertion routine. *
- * Based on: *
- * "Recursive proof of Boehm's knot insertion technique", by Phillip J Barry *
- * Ronald N Goldman, CAD, Volume 20 number 4 1988, pp 181-182. *
- * The original paper by Boehm W. is also referenced there. *
- *******************************************************************************
- * Written by Gershon Elber, Aug. 90. *
- ******************************************************************************/
-
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #include "cagd_loc.h"
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Returns a new curve refined at t (t is inserted as a new knot in Crv). M
- * If however the multiplicity of t in the current knot vector is equal M
- * (or greater!?) to the degree or t is not in the curve's parametric domain, M
- * no new knot is insert and NULL is returned instead. M
- * Control mesh is updated as follows (P is old ctl polygon, Q is new): M
- * Let Index be the last knot in old knot vector less than t and M
- * let j be j = Index - order + 1. Also let k be the curve order. Then, M
- * M
- * Case 1: Q(i) = P(i), i <= j V
- * V
- * t - t(i) t(i+k-1) - t V
- * case 2: Q(i) = --------------- P(i) + --------------- P(i-1), j<i<=Index V
- * t(i+k-1) - t(i) t(i+k-1) - t(i) V
- * V
- * case 3: Q(i) = P(i-1), Index < i V
- * M
- * Note: Altough works, this is not the optimal way to insert many knot! M
- * See also the BspKnotEvalAlpha set of routines. M
- * M
- * For more see: M
- * "Recursive proof of Boehm's knot insertion technique", by Phillip J Barry M
- * Ronald N Goldman, CAD, Volume 20 number 4 1988, pp 181-182. M
- * Which also references the original 1980 paper by Boehm. M
- * *
- * PARAMETERS: M
- * Crv: To refine by adding a new knot with value equal to t. If Crv M
- * is a periodic curve, it is first unwrapped to a float end M
- * condition curve. M
- * t: New knot to insert into Crv. M
- * *
- * RETURN VALUE: M
- * CagdCrvStruct *: The refined curve. M
- * *
- * KEYWORDS: M
- * BspCrvKnotInsert, refinement, knot insertion M
- *****************************************************************************/
- CagdCrvStruct *BspCrvKnotInsert(CagdCrvStruct *Crv, CagdRType t)
- {
- CagdBType
- NewCrv = FALSE,
- IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
- CagdRType *KnotVector;
- int i, j, Len, KVLen, Index,
- k = Crv -> Order,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdCrvStruct *RefinedCrv;
- CagdRType **Points, **NewPoints;
-
- if (CAGD_IS_PERIODIC_CRV(Crv)) {
- NewCrv = TRUE;
- Crv = CnvrtPeriodic2FloatCrv(Crv);
- }
-
- KnotVector = Crv -> KnotVector;
- Len = Crv -> Length;
- KVLen = k + Len;
- Index = BspKnotLastIndexL(KnotVector, KVLen, t);
- RefinedCrv = CagdCrvNew(Crv -> GType, Crv -> PType, Len + 1);
- Points = Crv -> Points;
- NewPoints = RefinedCrv -> Points;
-
- if (!BspKnotParamInDomain(KnotVector, Len, k, FALSE, t))
- CAGD_FATAL_ERROR(CAGD_ERR_T_NOT_IN_CRV);
-
- /* Update the rest of the RefinedCrv data structure (easy part). */
- RefinedCrv -> Order = k;
- RefinedCrv -> KnotVector = BspKnotInsertOne(Crv -> KnotVector, k, Len, t);
-
- /* Case 1: Copy all points upto (Index - Order + 1) as is. */
- for (i = IsNotRational; i <= MaxCoord; i++)
- CAGD_GEN_COPY(NewPoints[i], Points[i],
- sizeof(CagdRType) * (Index - k + 2));
-
- /* Case 2: Convex blend of exactly 2 points. */
- for (j = Index - k + 2; j <= Index; j++)
- for (i = IsNotRational; i <= MaxCoord; i++)
- NewPoints[i][j] =
- ((t - KnotVector[j]) * Points[i][j] +
- (KnotVector[j + k - 1] - t) * Points[i][j - 1]) /
- (KnotVector[j + k - 1] - KnotVector[j]);
-
- /* Case 3: Copy all points upto the end. */
- for (i = IsNotRational; i <= MaxCoord; i++)
- CAGD_GEN_COPY(&NewPoints[i][Index + 1],
- &Points[i][Index],
- sizeof(CagdRType) * (Len - Index));
-
- if (NewCrv)
- CagdCrvFree(Crv);
-
- return RefinedCrv;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Returns a new surface refined at t (t is inserted as a new knot in Srf) M
- * in parametric directipn Dir. See BspCrvKnotInsert for the mathematical M
- * background of this knot insertion algorithm. M
- * *
- * PARAMETERS: M
- * Srf: To refine by adding a new knot with value equal to t. If Srf M
- * is a periodic curve, it is first unwrapped to a float end M
- * condition curve. M
- * Dir: Of refinement, either U or V. M
- * t: New knot to insert into Srf. M
- * *
- * RETURN VALUE: M
- * CagdSrfStruct *: The refined surface. M
- * *
- * KEYWORDS: M
- * BspSrfKnotInsert, refinement, knot insertion M
- *****************************************************************************/
- CagdSrfStruct *BspSrfKnotInsert(CagdSrfStruct *Srf,
- CagdSrfDirType Dir,
- CagdRType t)
- {
- CagdBType
- NewSrf = FALSE;
- int Row, Col, ULength, VLength, UOrder, VOrder;
- CagdCrvStruct *Crv, *RefCrv;
- CagdSrfStruct
- *RefSrf = NULL;
-
- if (CAGD_IS_PERIODIC_SRF(Srf)) {
- NewSrf = TRUE;
- Srf = CnvrtPeriodic2FloatSrf(Srf);
- }
-
- ULength = Srf -> ULength;
- VLength = Srf -> VLength;
- UOrder = Srf -> UOrder;
- VOrder = Srf -> VOrder;
-
- switch (Dir) {
- case CAGD_CONST_U_DIR:
- RefSrf = BspSrfNew(ULength + 1, VLength, UOrder, VOrder,
- Srf -> PType);
- IritFree((VoidPtr) RefSrf -> UKnotVector);
- IritFree((VoidPtr) RefSrf -> VKnotVector);
- RefSrf -> VKnotVector = BspKnotCopy(Srf -> VKnotVector,
- Srf -> VLength + Srf -> VOrder);
-
- for (Row = 0; Row < VLength; Row++) {
- Crv = BspSrfCrvFromMesh(Srf, Row, CAGD_CONST_V_DIR);
- RefCrv = BspCrvKnotInsert(Crv, t);
-
- if (Row == 0) { /* Figure out refined knot vector. */
- RefSrf -> UKnotVector = BspKnotCopy(RefCrv -> KnotVector,
- RefCrv -> Length + RefCrv -> Order);
- }
-
- CagdCrvToMesh(RefCrv, Row, CAGD_CONST_V_DIR, RefSrf);
-
- CagdCrvFree(Crv);
- CagdCrvFree(RefCrv);
- }
- break;
- case CAGD_CONST_V_DIR:
- RefSrf = BspSrfNew(ULength, VLength + 1, UOrder, VOrder,
- Srf -> PType);
- IritFree((VoidPtr) RefSrf -> UKnotVector);
- IritFree((VoidPtr) RefSrf -> VKnotVector);
- RefSrf -> UKnotVector = BspKnotCopy(Srf -> UKnotVector,
- Srf -> ULength + Srf -> UOrder);
-
- for (Col = 0; Col < ULength; Col++) {
- Crv = BspSrfCrvFromMesh(Srf, Col, CAGD_CONST_U_DIR);
- RefCrv = BspCrvKnotInsert(Crv, t);
-
- if (Col == 0) { /* Figure out refined knot vector. */
- RefSrf -> VKnotVector = BspKnotCopy(RefCrv -> KnotVector,
- RefCrv -> Length + RefCrv -> Order);
- }
-
- CagdCrvToMesh(RefCrv, Col, CAGD_CONST_U_DIR, RefSrf);
-
- CagdCrvFree(Crv);
- CagdCrvFree(RefCrv);
- }
- break;
- default:
- CAGD_FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
- break;
- }
-
- if (NewSrf)
- CagdSrfFree(Srf);
-
- return RefSrf;
- }
-